﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using CaptchaMvc.HtmlHelpers;
using Doan.Forum.Common;
using Doan.Forum.Models;
using Ext.Net;
using Ext.Net.MVC;
using System.Linq.Dynamic;
using log4net;
using SortDirection = Ext.Net.SortDirection;

namespace Doan.Forum.Controllers
{
    [DirectController]
    public class AccountController : Controller
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(AccountController).Name);
        private static DoAnForumEntities db = new DoAnForumEntities();
        public IFormsAuthenticationService FormsService { get; set; }
        public IMembershipService MembershipService { get; set; }

        protected override void Initialize(RequestContext requestContext)
        {
            if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
            if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
            base.Initialize(requestContext);
        }


        // **************************************
        // URL: /Account/ForgotPassword
        // **************************************

        public ActionResult AcessDenied()
        {
            return View();
        }
        
        public ActionResult ForgotPassword()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ForgotPassword(ForgotPassword model)
        {
            if (ModelState.IsValid && this.IsCaptchaVerify("Captcha is not valid"))
            {
                MembershipUser user = Membership.GetUser(model.UserName);
                try
                {
                    if (user.Email != model.Email)
                    {
                        ViewBag.fogotpass = "Email cung cấp không hợp lệ";
                    }
                    else
                    {
                        var temp = db.aspnet_Users.Single(m => m.UserName == model.UserName);
                        string resetPass = temp.UserId.ToString().Substring(0, 8);
                        user.ChangePassword(user.ResetPassword(), resetPass);
                        var user1 = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
                        user1.Comment = "need change pass";
                        db.SaveChanges();
                        string body = "Chào bạn " + model.UserName + "!" + "\n Đây là mật khẩu của bạn : " + resetPass+"\n Vì yếu tố bảo mật, bạn cần đổi mật khẩu ở lần đăng nhập đầu tiên. Xin cảm ơn!";
                        string subject = "Cấp lại mật khẩu diễn đàn ungthuvn";
                        try
                        {
                            ForgotPassService.SendMail(model.Email, body, subject);
                            ViewBag.fogotpasssucc = "Mật khẩu mới đã được gửi đến email của bạn. Hãy kiểm tra email để lấy lại mật khẩu.";
                            return View();
                        }
                        catch (Exception ex)
                        {
                            log.Error("Can't send email: " + ex.Message);
                            ViewBag.fogotpass = "Không thể gửi mail. Tên đăng nhập hoặc email không hợp lệ.";
                        }
                    }
                }
                catch (Exception)
                {
                    ViewBag.fogotpass = "Tên đăng nhập không chính xác";
                }
                
            }
            else
            {
                ViewBag.fogotpass = "Lỗi, hãy thực hiện lại";
            }

            // If we got this far, something failed, redisplay form
            return View();
        }

        // **************************************
        // URL: /Account/LogOff
        // **************************************

        public ActionResult LogOff()
        {
            FormsService.SignOut();
            return RedirectToAction("Index", "Home");
        }

        // **************************************
        // URL: /Account/LogOn
        // **************************************

        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (MembershipService.ValidateUser(model.UserName, model.Password))
                {
                    FormsService.SignIn(model.UserName, model.RememberMe);
                    var temp = db.aspnet_Users.Single(m => m.UserName == model.UserName);
                    var user = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
                    const string comment = "need change pass";
                    if (user.Comment != null)
                    {
                        string test = user.Comment.ToString(CultureInfo.InvariantCulture);
                        if(comment.Equals(test))
                        {
                            return RedirectToAction("ChangePassword");
                        }
                    }
                    else if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    var crrUser = db.aspnet_Users.SingleOrDefault(x => model.UserName.Equals(x.UserName));
                    if(crrUser!=null)
                    {
                        var crrMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == crrUser.UserId);
                        if (!crrMember.IsApproved) ViewBag.LogonErr = "Tài khoản của bạn chưa được kích hoạt. Vui lòng kiểm tra lại email để kích hoạt tài khoản. Nếu bạn chưa nhận được email, hãy bấm 'Gửi lại mã kích hoạt' để nhận lại mã xác nhận. Xin cảm ơn!";
                        else
                        {
                            ViewBag.LogonErr = "Đăng nhập thất bại. Mật khẩu không chính xác";
                        }
                    }
                    else
                    {
                        ViewBag.LogonErr = "Đăng nhập thất bại. Tên đăng nhập không chính xác";
                    }
                }
            }

            // If we got this far, something failed, redisplay form
            return View();
        }

        // **************************************
        // URL: /Account/Register
        // **************************************

        //[AccessDeniedAuthorize(Roles = "Admin")]
        public ActionResult Register()
        {
            return View();
        }

        //[Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    Roles.AddUserToRoles(model.UserName, new[] {"Member"});
                    var user = new User();
                    var temp = db.aspnet_Users.SingleOrDefault(x => x.UserName == model.UserName);
                    if (temp != null)
                    {
                        user.UserId = temp.UserId;
                        user.UserSignature = model.UserSignature;
                        user.UserBirthDate = model.BirthDay;

                        try
                        {
                            var image = WebImage.GetImageFromRequest("upImage");
                            if (image != null)
                            {
                                if (image.Width > 100)
                                {
                                    image.Resize(100, 100);

                                }
                                var filename = Server.MapPath("~/") + "//Content//Logo//" + image.FileName;
                                image.Save(filename); //Lưu ảnh trên server
                                user.UserPhoto = "/Content/Logo/" + image.FileName;
                            }
                            else
                            {
                                var filename = "/Content/Logo/defaultLogo.jpg";
                                user.UserPhoto = filename;
                            }
                        }
                        catch (Exception)
                        {
                            var filename = "/Content/Logo/defaultLogo.jpg";
                            user.UserPhoto = filename;
                        }
                        
                        db.Users.AddObject(user);
                        db.SaveChanges();
                    }

                    EmailManager.SendConfirmationEmail(model.UserName);

                    ViewBag.registerSucc =
                        "Tài khoản của bạn đã được tạo thành công. Hãy kiểm tra email để kích hoạt tài khoản.";
                    return View();
                }
                else
                {
                    string error = AccountValidation.ErrorCodeToString(createStatus);
                    ViewBag.registerErr =error;
                    log.Error("ERROR: "+error);
                }
            }

            return View(model);
        }

        public ActionResult Verify(string id)
        {
            if (string.IsNullOrEmpty(id) || (!Regex.IsMatch(id, @"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}")))
            {
                ViewBag.Msg = "Not Good!!!";
                return View();
            }

            else
            {
                var user = Membership.GetUser(new Guid(id));

                if (!user.IsApproved)
                {
                    user.IsApproved = true;
                    Membership.UpdateUser(user);
                    FormsAuthentication.SetAuthCookie(user.UserName, false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    FormsAuthentication.SignOut();
                    ViewBag.Msg = "Tài khoản đã được kích hoạt";
                    return RedirectToAction("LogOn");
                }
            }
        }

        [HttpGet]
        public ActionResult ResendConfirm()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ResendConfirm(ResendConfirmModel model)
        {
            if (this.IsCaptchaVerify("Captcha is not valid"))
            {
                var crrUser = db.aspnet_Users.SingleOrDefault(x => model.UserName.Equals(x.UserName));
                if (crrUser != null)
                {
                    var crrMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == crrUser.UserId);
                    if (crrMember.IsApproved)
                    {
                        ViewBag.ResendSucc =
                            "Tài khoản của bạn đã được kích hoạt rồi. Hãy đăng nhập để tham gia diễn đàn!";
                    }
                    else
                    {
                        EmailManager.SendConfirmationEmail(model.UserName);
                        ViewBag.ResendSucc =
                            "Mã xác nhận đã được gửi đến email của bạn. Hãy kiểm tra email để kích hoạt tài khoản!";
                    }
                }
                else
                {
                    ViewBag.ResendErr = "Tên đăng nhập không tồn tại";
                }
            }
            else
            {
                ViewBag.ResendErr = "Mã xác nhận không chính xác";
            }
            return View();
        }


        // **************************************
        // URL: /Account/ChangePassword
        // **************************************

        [Authorize]
        public ActionResult ChangePassword()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                
                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    var temp = db.aspnet_Users.Single(m => m.UserName == User.Identity.Name);
                    var user1 = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
                    user1.Comment = null;
                    db.SaveChanges();
                    ViewBag.ChangePassSucc = "Mật khẩu đã được đổi thành công";
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                    ViewBag.ChangePassErr = "Mật khẩu cung cấp không chính xác";
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }


        [Authorize]
        public ActionResult ChangePasswordAdmin()
        {
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePasswordAdmin(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {

                if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
                {
                    return RedirectToAction("ChangePasswordStatus");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                    X.Msg.Alert("Error!", "Mật khẩu cung cấp không chính xác").Show();
                }
            }

            // If we got this far, something failed, redisplay form
            ViewBag.PasswordLength = MembershipService.MinPasswordLength;
            return this.FormPanel();
        }

        public ActionResult ChangePasswordStatus()
        {
            var temp = db.aspnet_Users.Single(m => m.UserName == User.Identity.Name);
            var user1 = db.aspnet_Membership.Single(m => m.UserId == temp.UserId);
            user1.Comment = null;
            db.SaveChanges();
            return RedirectToAction("ChangePasswordSuccess");
        }

        // **************************************
        // URL: /Account/ChangePasswordSuccess
        // **************************************

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        // **************************************
        // URL: /Account/ListAcount
        // **************************************

        [AccessDeniedAuthorize(Roles = "Admin")]
        public ActionResult ListAcount()
        {
            Session["includeInActiveAccount"] = false;
            Session["CharFilterAccount"] = "";

            return View();
        }

        public ActionResult IncludeInActive()
        {
            var store = X.GetCmp<Store>("AccountStore");

            Session["includeInActiveAccount"] = !(bool)Session["includeInActiveAccount"];

            store.Reload();
            return this.Direct();
        }

        [DirectMethod]
        public ActionResult InActiveAccount(string a)
        {
            string test = "\"";
            var store = X.GetCmp<Store>("AccountStore");
            for (int i = 2; i < (a.Length-1); i++)
            {
                if (','.Equals(a[i])) i += 2;
                string temp = null;
                while (!(','.Equals(a[i])) && !(']'.Equals(a[i])) && !(test.Equals(a[i].ToString())))
                {
                    temp = temp + a[i];
                    i++;
                }
                aspnet_Users user = db.aspnet_Users.Single(c => c.UserName.Equals(temp));
                aspnet_Membership member = db.aspnet_Membership.Single(c => c.UserId == user.UserId);
                db.aspnet_Membership.Detach(member);
                member.IsApproved = !member.IsApproved;
                db.aspnet_Membership.Attach(member);
                db.ObjectStateManager.ChangeObjectState(member, EntityState.Modified);
                db.SaveChanges();
            }
            X.Msg.Notify("Thành công", "Sửa thành công!").Show();
            store.Reload();
            return this.FormPanel();
        }

        [DirectMethod]
        public ActionResult CharFilterAccount(string filterstring)
        {
            var store = X.GetCmp<Store>("AccountStore");
            Session["CharFilterAccount"] = filterstring;
            store.Reload();
            return this.Direct();
        }

        public ActionResult BindingStore(StoreRequestParameters parameters)
        {
            var sampleData = (from tab1 in db.aspnet_Membership
                              join tab2 in db.aspnet_Users on tab1.UserId equals tab2.UserId
                              select new
                              {
                                  tab1.UserId,
                                  tab2.UserName,
                                  tab1.Email,
                                  tab1.CreateDate,
                                  Role=tab2.aspnet_Roles.Select(x=>x.RoleName),
                                  tab1.IsApproved
                              }
            );

            bool includeInActive = (bool)Session["includeInActiveAccount"];
            string charFilter = (string)Session["CharFilterAccount"];

            var result = sampleData.Where(ent => ((includeInActive || ent.IsApproved)));
            if ("0".Equals(charFilter))
            {
                result = sampleData.Where(ent => ((includeInActive || ent.IsApproved) &&
                    (ent.UserName.StartsWith("0") || ent.UserName.StartsWith("1") ||
                    ent.UserName.StartsWith("2") || ent.UserName.StartsWith("3") ||
                    ent.UserName.StartsWith("4") || ent.UserName.StartsWith("5") ||
                    ent.UserName.StartsWith("6") || ent.UserName.StartsWith("7") ||
                    ent.UserName.StartsWith("8") || ent.UserName.StartsWith("9")
                    )));
            }

            else
            {
                result = sampleData.Where(ent => ((includeInActive || (bool)ent.IsApproved) && ent.UserName.StartsWith(charFilter)));

            }

            // Sorting
            if (!string.IsNullOrEmpty(parameters.SimpleSort))
            {
                result = result.OrderBy(parameters.SimpleSort + (parameters.SimpleSortDirection == SortDirection.DESC ? " desc" : " asc"));
            }
            else
            {
                result = result.OrderBy(ent => ent.UserId);
            }

            // Paging
            int limit = parameters.Limit;
            if ((parameters.Start + parameters.Limit) > result.Count())
            {
                limit = result.Count() - parameters.Start;
            }

            var rangeData = (parameters.Start < 0 || limit < 0) ? result : result.Skip(parameters.Start).Take(limit);
            return this.Store(rangeData.Select(ent => new { ent.UserId, ent.UserName, ent.Email, ent.CreateDate, ent.Role,ent.IsApproved }), result.Count());
        }

        // **************************************
        // URL: /Account/Profile
        // **************************************

        public ActionResult MyProfile()
        {
            var profile = new ProfileModel();
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var role = aspUser.aspnet_Roles.FirstOrDefault().RoleName;
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.CreateDate = aspMember.CreateDate;
            profile.Birthday = user.UserBirthDate;
            profile.Post = db.Comments.Count(x => x.UserId == aspUser.UserId);
            profile.Role = role;
            return View(profile);
        }
        [HttpGet]
        public ActionResult EditProfile()
        {
            var profile = new ProfileModel();
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.Birthday = user.UserBirthDate;
            profile.Avatar = user.UserPhoto;
            return View(profile);
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult EditProfile(ProfileModel model)
        {
            var id = User.Identity.Name;
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == id);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            aspUser.UserName = model.UserName;
            aspMember.Email = model.Email;
            user.UserBirthDate = model.Birthday;
            user.UserSignature = model.UserSignature;
            var upImage = X.GetCmp<FileUploadField>("UpImage");
            if (upImage.HasFile)
            {
                var httpPostedFileBase = Request.Files[0];
                if (httpPostedFileBase != null)
                {
                    httpPostedFileBase.SaveAs(Server.MapPath("~/") + "//Content//Logo//" +
                                              httpPostedFileBase.FileName);
                    user.UserPhoto = "/Content/Logo/" + httpPostedFileBase.FileName;
                }
            }
            db.SaveChanges();
            return View();
        }

        public ActionResult ShowProfile(string userName)
        {
            var profile = new ProfileModel();
            var aspUser = db.aspnet_Users.SingleOrDefault(x => x.UserName == userName);
            var user = db.Users.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var aspMember = db.aspnet_Membership.SingleOrDefault(x => x.UserId == aspUser.UserId);
            var role = aspUser.aspnet_Roles.FirstOrDefault().RoleName;
            profile.UserName = aspUser.UserName;
            profile.Email = aspMember.Email;
            profile.Avatar = user.UserPhoto;
            profile.UserSignature = user.UserSignature;
            profile.CreateDate = aspMember.CreateDate;
            profile.Birthday = user.UserBirthDate;
            profile.Post = db.Comments.Count(x => x.UserId == aspUser.UserId);
            profile.Role = role;
            return View(profile);
        }

        [DirectMethod]
        public ActionResult SetMod(string username)
        {
            var store = X.GetCmp<Store>("AccountStore");
            try
            {
                Roles.RemoveUserFromRole(username, "Member");
                Roles.AddUserToRole(username, "Mod");
            }
            catch (Exception)
            {

                X.Msg.Alert("Lỗi", "Thành viên này đã được cấp quyền rồi!").Show();
            }
            store.Reload();
            return this.FormPanel();
        }

        [DirectMethod]
        public ActionResult SetAdmin(string username)
        {
            var store = X.GetCmp<Store>("AccountStore");
            try
            {
                Roles.RemoveUserFromRole(username, "Member");
                //Roles.RemoveUserFromRole(username, "Mod");
                Roles.AddUserToRole(username, "Admin");
            }
            catch (Exception)
            {

                X.Msg.Alert("Lỗi", "Thành viên này đã được cấp quyền rồi!").Show();
            }
            store.Reload();
            return this.FormPanel();
        }
    }
}
